<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title></title>
</head>
<body>
<script type="text/javascript">
    /*
    * 装饰者模式中，可以在运行时动态添加副将功能到对象中
    *
    * */

    // eg:
     var  Sale = function(price) {
         this.price = price || 100;
     };

    Sale.prototype.getPrice = function() {
        return this.price;
    };
    // 装饰着对象   ------------！！！---------、
    Sale.decorators = {};
    // 示例：首先会从父对象中获取值，再改变值
    Sale.decorators.fedtax = {
        getPrice: function() {
            var price = this.uber.getPrice();
            price += price * 5 / 100;
            return price;
        }
    };
     // 他们的作用非常多啊
    Sale.decorators.quebec = {
        getPrice: function() {
            var price = this.uber.getPrice();
            price += price * 7.5 / 100;
            return price;
        }
    };
    Sale.decorators.money = {
        getPrice: function() {
            var price = this.uber.getPrice();
            return "$" + price.toFixed(2);
        }
    };
    Sale.decorators.cdn = {
        getPrice: function() {
            var price = this.uber.getPrice();
            return "$" + price.toFixed(2);
        }
    };
    // 装饰构建方法
    Sale.prototype.decorate = function(decorator) {
        var F = function() {}, i = null, obj = null, overrides = this.constructor.decorators[decorator];
        console.log(this,this.constructor);
        F.prototype = this;
        obj = new F();
        obj.uber = this;
        for(i in overrides) {
            if (overrides.hasOwnProperty(i)){
                obj[i] = overrides[i];
            }
        };
        return obj;
    };
    var sale = new Sale(100);
    sale = sale.decorate("fedtax");
    sale = sale.decorate("quebec");
    sale = sale.decorate("money");
    console.log(sale.getPrice());
    console.log(sale.price);

    // 第二种装饰构建方法，相比较第一种，此方法不用继承和构造父类属性，使用列表实现，
    // 此时主要靠getPrice方法实现装饰，同时增加一个decorators_list的属性用来存放已添加的装饰方法
    var SaleSale = function(price) {
        this.price = price || 1000;
        this.decorators_list = [];
    };

    SaleSale.prototype.decorate = function(decorator) {
        this.decorators_list.push(decorator);
    };
    SaleSale.decorators = {};
    // 示例：首先会从父对象中获取值，再改变值
    SaleSale.decorators.fedtax = {
        getPrice: function(price) {
            price += price * 5 / 100;
            return price;
        }
    };
    // 他们的作用非常多啊
    SaleSale.decorators.quebec = {
        getPrice: function(price) {
            price += price * 7.5 / 100;
            return price;
        }
    };
    SaleSale.decorators.money = {
        getPrice: function(price) {
            return "$" + price.toFixed(2);
        }
    };
    SaleSale.decorators.cdn = {
        getPrice: function(price) {
            return "$" + price.toFixed(2);
        }
    };
    SaleSale.prototype.getPrice = function() {
        var price = this.price, i = null, max = this.decorators_list.length, name = null;
        for(i = 0; i < max; i++) {
            name = this.decorators_list[i];
            price = SaleSale.decorators[name].getPrice(price);
        }
        return price;
    };
    var sss = new SaleSale(100);
    sss.decorate("fedtax");
    sss.decorate("quebec");
    sss.decorate("money");
    console.log(sss.getPrice());
</script>
</body>
</html>